package org.mall.modules.system.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.mall.common.aspect.annotation.IPLimit;
import org.mall.common.exception.JeecgBootException;
import org.mall.common.util.RedisUtil;
import org.mall.common.util.SpringContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class RequestLimitContract {
    @Autowired
    private RedisUtil redisUtil;

    @Pointcut("@annotation(org.mall.common.aspect.annotation.IPLimit)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        requestLimit(point);

        return result;
    }


    public void requestLimit(final JoinPoint joinPoint)  throws JeecgBootException {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            IPLimit limit=method.getAnnotation(IPLimit.class);
            HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
            String ip = request.getLocalAddr();
            String url = request.getRequestURL().toString();
            String key = "reqlimit".concat(url).concat(ip);
            if(redisUtil.getLimitIpCount(key)==null || redisUtil.getLimitIpCount(key)==0){
                redisUtil.set(key,1,limit.time());
            }else
            {
                redisUtil.set(key,redisUtil.getLimitIpCount(key)+1,limit.time());
            }
            int count = redisUtil.getLimitIpCount(key);
            if (count > limit.count()) {
                log.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
                throw new JeecgBootException("请求过于频繁");
            }
        }
        catch (JeecgBootException e) {
            throw e;
        }
        catch (Exception e) {
            log.error("发生异常: ", e);
        }
    }
}
